En omfattande guide till Cross-Origin Resource Sharing (CORS), som tÀcker konfiguration, sÀkerhetsimplikationer och bÀsta praxis för utvecklare.
Cross-Origin Resource Sharing (CORS): Konfiguration och bÀsta praxis för sÀkerhet
Inom webbutveckling Àr sÀkerhet av yttersta vikt. En kritisk aspekt av webbsÀkerhet Àr att hantera hur webbsidor frÄn ett ursprung kan komma Ät resurser frÄn ett annat ursprung. Det Àr hÀr Cross-Origin Resource Sharing (CORS) kommer in i bilden. CORS Àr en sÀkerhetsfunktion i webblÀsare som begrÀnsar webbsidor frÄn att göra förfrÄgningar till en annan domÀn Àn den som serverade webbsidan. Denna mekanism finns för att förhindra att skadliga webbplatser kommer Ät kÀnslig data. Den hÀr artikeln ger en omfattande guide till CORS, som tÀcker dess konfiguration, sÀkerhetsimplikationer och bÀsta praxis.
FörstÄ Same-Origin Policy
CORS bygger pÄ grunden av Same-Origin Policy (samma ursprungsprincip), en grundlÀggande sÀkerhetsmekanism som implementeras av webblÀsare. Samma ursprungsprincip begrÀnsar webbsidor frÄn att göra förfrÄgningar till en annan domÀn Àn den som serverade webbsidan. TvÄ URL:er anses ha samma ursprung om de har samma protokoll (t.ex. HTTP eller HTTPS), vÀrd (t.ex. example.com) och port (t.ex. 80 eller 443). Till exempel:
http://example.comochhttp://example.com/pathhar samma ursprung.http://example.comochhttps://example.comhar olika ursprung (olika protokoll).http://example.comochhttp://www.example.comhar olika ursprung (olika vÀrdar).http://example.com:80ochhttp://example.com:8080har olika ursprung (olika portar).
Samma ursprungsprincip Àr utformad för att förhindra Cross-Site Scripting (XSS)-attacker, dÀr en skadlig webbplats injicerar skript i en betrodd webbplats för att stjÀla anvÀndardata eller utföra obehöriga ÄtgÀrder. Utan samma ursprungsprincip skulle en skadlig webbplats potentiellt kunna komma Ät dina bankkontouppgifter om du var inloggad pÄ din internetbank i en annan flik.
Vad Àr Cross-Origin Resource Sharing (CORS)?
Ăven om samma ursprungsprincip Ă€r avgörande för sĂ€kerheten, kan den ocksĂ„ vara restriktiv i legitima scenarier dĂ€r webbplatser behöver komma Ă„t resurser frĂ„n olika ursprung. Till exempel kan en webbapplikation som hostas pĂ„ example.com behöva hĂ€mta data frĂ„n ett API som hostas pĂ„ api.example.net. CORS tillhandahĂ„ller en mekanism för att kringgĂ„ samma ursprungsprincip pĂ„ ett kontrollerat sĂ€tt, vilket gör att webbsidor kan göra förfrĂ„gningar mellan olika ursprung nĂ€r servern uttryckligen godkĂ€nt det.
CORS fungerar genom att lÀgga till HTTP-headers i svaret frÄn servern, vilket indikerar vilka ursprung som tillÄts komma Ät resursen. WebblÀsaren kontrollerar sedan dessa headers och blockerar förfrÄgan om ursprunget för webbsidan som gör förfrÄgan inte Àr tillÄtet.
Hur CORS fungerar: HTTP-headers
CORS förlitar sig pÄ specifika HTTP-headers för att underlÀtta förfrÄgningar mellan olika ursprung. HÀr Àr de viktigaste headers som Àr involverade:
1. Origin (Request Header)
Origin-headern skickas av webblÀsaren i förfrÄgningar mellan olika ursprung. Den indikerar ursprunget (protokoll, vÀrd och port) för webbsidan som gör förfrÄgan. Till exempel:
Origin: http://example.com
2. Access-Control-Allow-Origin (Response Header)
Access-Control-Allow-Origin-headern Àr den viktigaste headern i CORS. Den specificerar vilka ursprung som tillÄts komma Ät resursen. Den kan ha ett av följande vÀrden:
- Ett specifikt ursprung: Till exempel,
Access-Control-Allow-Origin: http://example.comtillÄter endast förfrÄgningar frÄnhttp://example.com. *(jokertecken):Access-Control-Allow-Origin: *tillÄter förfrÄgningar frÄn vilket ursprung som helst. Detta bör anvÀndas med försiktighet, eftersom det i praktiken inaktiverar samma ursprungsprincip för den resursen.
Exempel:
Access-Control-Allow-Origin: https://www.example.com
3. Access-Control-Allow-Methods (Response Header)
Access-Control-Allow-Methods-headern specificerar de HTTP-metoder (t.ex. GET, POST, PUT, DELETE) som Àr tillÄtna i förfrÄgan mellan olika ursprung. Detta krÀvs för preflight-förfrÄgningar (förklaras nedan).
Exempel:
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
4. Access-Control-Allow-Headers (Response Header)
Access-Control-Allow-Headers-headern specificerar de HTTP-headers som Àr tillÄtna i förfrÄgan mellan olika ursprung. Detta krÀvs ocksÄ för preflight-förfrÄgningar.
Exempel:
Access-Control-Allow-Headers: Content-Type, Authorization, X-Requested-With
5. Access-Control-Allow-Credentials (Response Header)
Access-Control-Allow-Credentials-headern specificerar om webblÀsaren ska inkludera autentiseringsuppgifter (t.ex. cookies, authorization-headers) i förfrÄgan mellan olika ursprung. Den kan ha ett av tvÄ vÀrden: true eller false. Om true Àr satt, kan Access-Control-Allow-Origin-headern inte sÀttas till *. Den mÄste vara ett specifikt ursprung.
Exempel:
Access-Control-Allow-Credentials: true
6. Access-Control-Max-Age (Response Header)
Access-Control-Max-Age-headern specificerar antalet sekunder som webblÀsaren kan cacha resultaten frÄn preflight-förfrÄgan. Detta kan förbÀttra prestandan genom att minska antalet preflight-förfrÄgningar.
Exempel:
Access-Control-Max-Age: 3600
Enkla förfrÄgningar vs. Preflight-förfrÄgningar
CORS skiljer mellan tvÄ typer av förfrÄgningar mellan olika ursprung: enkla förfrÄgningar och preflight-förfrÄgningar.
Enkla förfrÄgningar
En enkel förfrÄgan Àr en förfrÄgan som uppfyller följande kriterier:
- Metoden Àr
GET,HEAD, ellerPOST. - Om metoden Àr
POST, ÀrContent-Type-headern en av följande:application/x-www-form-urlencoded,multipart/form-data, ellertext/plain. - FörfrÄgan sÀtter inga anpassade headers (förutom de som automatiskt sÀtts av webblÀsaren).
För enkla förfrÄgningar skickar webblÀsaren förfrÄgan direkt till servern. Servern svarar sedan med lÀmpliga CORS-headers. Om ursprunget Àr tillÄtet, bearbetar webblÀsaren svaret. Annars blockerar webblÀsaren svaret och kastar ett fel.
Preflight-förfrÄgningar
En preflight-förfrÄgan skickas av webblÀsaren innan den faktiska förfrÄgan mellan olika ursprung görs om förfrÄgan inte uppfyller kriterierna för en enkel förfrÄgan. Detta hÀnder vanligtvis nÀr förfrÄgan anvÀnder en annan metod Àn GET, HEAD, eller POST, eller nÀr förfrÄgan sÀtter anpassade headers.
Preflight-förfrÄgan Àr en OPTIONS-förfrÄgan som inkluderar följande headers:
Origin: Ursprunget för webbsidan som gör förfrÄgan.Access-Control-Request-Method: HTTP-metoden som kommer att anvÀndas i den faktiska förfrÄgan.Access-Control-Request-Headers: En kommaseparerad lista över de anpassade headers som kommer att anvÀndas i den faktiska förfrÄgan.
Servern svarar sedan med följande headers:
Access-Control-Allow-Origin: Ursprunget som tillÄts komma Ät resursen.Access-Control-Allow-Methods: De HTTP-metoder som Àr tillÄtna i förfrÄgan mellan olika ursprung.Access-Control-Allow-Headers: De HTTP-headers som Àr tillÄtna i förfrÄgan mellan olika ursprung.Access-Control-Max-Age: Antalet sekunder som webblÀsaren kan cacha resultaten frÄn preflight-förfrÄgan.
Om servern svarar med lÀmpliga CORS-headers, fortsÀtter webblÀsaren med den faktiska förfrÄgan mellan olika ursprung. Annars blockerar webblÀsaren förfrÄgan och kastar ett fel.
Exempel pÄ CORS-konfiguration
Implementeringen av CORS varierar beroende pÄ den server-side-teknik du anvÀnder. HÀr Àr nÄgra exempel för vanliga server-side-sprÄk och ramverk:
Node.js med Express
Att anvÀnda cors-mellanprogrammet Àr ett vanligt sÀtt att konfigurera CORS i Node.js med Express:
const express = require('express');
const cors = require('cors');
const app = express();
// Aktivera CORS för alla ursprung
app.use(cors());
// Aktivera CORS för ett specifikt ursprung
// app.use(cors({ origin: 'http://example.com' }));
// Aktivera CORS med alternativ
// app.use(cors({
// origin: ['http://example.com', 'http://localhost:3000'],
// methods: ['GET', 'POST', 'PUT', 'DELETE'],
// allowedHeaders: ['Content-Type', 'Authorization'],
// credentials: true
// }));
app.get('/api/data', (req, res) => {
res.json({ message: 'Hello from the API!' });
});
app.listen(3001, () => {
console.log('Server listening on port 3001');
});
Python med Flask
Du kan anvÀnda Flask-CORS-tillÀgget för att konfigurera CORS i Flask:
from flask import Flask
from flask_cors import CORS
app = Flask(__name__)
# Aktivera CORS för alla ursprung
CORS(app)
# Aktivera CORS för specifika ursprung
# CORS(app, origins=['http://example.com', 'http://localhost:3000'])
@app.route('/api/data')
def get_data():
return {'message': 'Hello from the API!'}
if __name__ == '__main__':
app.run(port=3001)
Java med Spring Boot
Spring Boot erbjuder flera sÀtt att konfigurera CORS. En metod Àr att anvÀnda @CrossOrigin-annoteringen:
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@CrossOrigin(origins = "http://example.com") // Specifikt ursprung
public class ApiController {
@GetMapping("/api/data")
public String getData() {
return "Hello from the API!";
}
}
// Global CORS-konfiguration (med WebMvcConfigurer):
// @Configuration
// public class CorsConfig implements WebMvcConfigurer {
// @Override
// public void addCorsMappings(CorsRegistry registry) {
// registry.addMapping("/**")
// .allowedOrigins("http://example.com", "http://localhost:3000")
// .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
// .allowedHeaders("Content-Type", "Authorization")
// .allowCredentials(true)
// .maxAge(3600);
// }
// }
PHP
I PHP kan du sÀtta CORS-headers direkt i ditt skript:
<?php
header("Access-Control-Allow-Origin: http://example.com");
header("Content-Type: application/json");
$data = array("message" => "Hello from the API!");
echo json_encode($data);
?>
SĂ€kerhetsaspekter med CORS
Ăven om CORS möjliggör förfrĂ„gningar mellan olika ursprung Ă€r det avgörande att förstĂ„ sĂ€kerhetsimplikationerna och implementera det korrekt för att undvika sĂ„rbarheter.
1. Undvik att anvÀnda Access-Control-Allow-Origin: * i produktion
Att anvÀnda jokertecknet * i Access-Control-Allow-Origin-headern tillÄter förfrÄgningar frÄn vilket ursprung som helst, vilket i praktiken inaktiverar samma ursprungsprincip för den resursen. Detta kan exponera ditt API för skadliga webbplatser som potentiellt kan stjÀla anvÀndardata eller utföra obehöriga ÄtgÀrder. Ange istÀllet de exakta ursprung som tillÄts komma Ät resursen. Till exempel, om din webbapplikation hostas pÄ example.com och behöver komma Ät ett API som hostas pÄ api.example.com, sÀtt headern till Access-Control-Allow-Origin: http://example.com.
Globalt exempel: FörestÀll dig ett API för en finansiell tjÀnst som sÀtter Access-Control-Allow-Origin: *. En skadlig webbplats skulle dÄ kunna göra förfrÄgningar till detta API pÄ uppdrag av en inloggad anvÀndare, och potentiellt överföra pengar utan anvÀndarens vetskap.
2. Validera Origin-headern pÄ servern
Ăven om du specificerar en lista över tillĂ„tna ursprung Ă€r det viktigt att validera Origin-headern pĂ„ servern för att förhindra att angripare förfalskar ursprunget. En angripare skulle potentiellt kunna skicka en förfrĂ„gan med en förfalskad Origin-header för att kringgĂ„ CORS-kontrollerna. För att mildra detta, jĂ€mför Origin-headern med en lista över betrodda ursprung pĂ„ serversidan. Om ursprunget inte finns i listan, avvisa förfrĂ„gan.
Globalt exempel: TÀnk dig en e-handelsplattform. En angripare skulle kunna försöka efterlikna en legitim butiks Origin för att komma Ät kÀnslig kunddata frÄn e-handelsplattformens API.
3. Var försiktig med Access-Control-Allow-Credentials: true
Om du sÀtter Access-Control-Allow-Credentials: true, kan Access-Control-Allow-Origin-headern inte sÀttas till *. Den mÄste vara ett specifikt ursprung. Detta beror pÄ att tillÄtelse av autentiseringsuppgifter frÄn vilket ursprung som helst kan skapa en sÀkerhetsrisk, eftersom det kan tillÄta skadliga webbplatser att komma Ät anvÀndardata om de kan lura en anvÀndare att besöka deras webbplats medan anvÀndaren ocksÄ Àr inloggad pÄ mÄlwebbplatsen. Denna instÀllning Àr viktig nÀr man hanterar cookies eller authorization-headers.
Globalt exempel: En social medieplattform som tillÄter förfrÄgningar mellan olika ursprung med autentiseringsuppgifter krÀver noggrann hantering för att förhindra obehörig Ätkomst till anvÀndarkonton.
4. Konfigurera Access-Control-Allow-Methods och Access-Control-Allow-Headers korrekt
TillÄt endast de HTTP-metoder och headers som Àr nödvÀndiga för förfrÄgningarna mellan olika ursprung. Om du bara behöver tillÄta GET- och POST-förfrÄgningar, tillÄt inte PUT, DELETE, eller andra metoder. PÄ samma sÀtt, tillÄt endast de specifika headers som din applikation behöver. Alltför tillÄtande konfigurationer kan öka risken för attacker.
Globalt exempel: Ett CRM-system bör endast exponera de nödvÀndiga API-slutpunkterna och headers för auktoriserade tredjepartsintegrationer, vilket minimerar attackytan.
5. AnvÀnd HTTPS för sÀker kommunikation
AnvÀnd alltid HTTPS för sÀker kommunikation mellan webblÀsaren och servern. HTTPS krypterar data som överförs mellan webblÀsaren och servern, vilket förhindrar avlyssning och man-in-the-middle-attacker. Att anvÀnda HTTP kan exponera kÀnslig data för angripare, Àven om CORS Àr korrekt konfigurerat.
Globalt exempel: SjukvÄrdsapplikationer mÄste anvÀnda HTTPS för att skydda patientdata som överförs mellan olika ursprung.
6. Content Security Policy (CSP)
Ăven om det inte Ă€r direkt relaterat till CORS, Ă€r Content Security Policy (CSP) en annan viktig sĂ€kerhetsmekanism som kan hjĂ€lpa till att förhindra XSS-attacker. CSP lĂ„ter dig definiera en vitlista över kĂ€llor frĂ„n vilka webblĂ€saren fĂ„r ladda resurser. Detta kan hjĂ€lpa till att förhindra angripare frĂ„n att injicera skadliga skript i din webbplats, Ă€ven om de lyckas kringgĂ„ andra sĂ€kerhetsĂ„tgĂ€rder.
Globalt exempel: Finansiella institutioner anvÀnder ofta strikta CSP-policyer för att begrÀnsa kÀllorna till innehÄll som laddas pÄ deras internetbanksportaler, vilket minskar risken för XSS-attacker.
Vanliga CORS-problem och felsökning
CORS-fel kan vara frustrerande att felsöka. HÀr Àr nÄgra vanliga problem och hur man felsöker dem:
1. "No 'Access-Control-Allow-Origin' header is present on the requested resource."
Detta Àr det vanligaste CORS-felet. Det indikerar att servern inte returnerar Access-Control-Allow-Origin-headern i sitt svar. Se till att servern Àr konfigurerad att skicka korrekta CORS-headers för ursprunget för webbsidan som gör förfrÄgan. Dubbelkolla din server-side-kod och konfigurationsfiler.
2. "Response to preflight request doesn't pass access control check: It does not have HTTP ok status."
Detta fel indikerar att preflight-förfrÄgan misslyckades. Detta kan hÀnda om servern inte svarar pÄ OPTIONS-förfrÄgningar eller om servern returnerar en felstatuskod (t.ex. 404, 500) som svar pÄ preflight-förfrÄgan. Se till att din server Àr konfigurerad för att hantera OPTIONS-förfrÄgningar och att den returnerar en 200 OK-statuskod.
3. "Response to preflight request doesn't pass access control check: The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'."
Detta fel intrÀffar nÀr du försöker skicka autentiseringsuppgifter (t.ex. cookies) i en förfrÄgan mellan olika ursprung och Access-Control-Allow-Origin-headern Àr satt till *. Som nÀmnts tidigare kan du inte anvÀnda jokertecknet * nÀr du skickar autentiseringsuppgifter. Du mÄste specificera det exakta ursprunget som tillÄts komma Ät resursen.
4. WebblÀsarcache
WebblÀsare kan cacha CORS-svar, vilket kan leda till ovÀntat beteende om CORS-konfigurationen Àndras. För att förhindra cacheproblem, sÀtt Cache-Control-headern i svaret till no-cache, no-store, eller max-age=0. Du kan ocksÄ anvÀnda Access-Control-Max-Age-headern för att kontrollera hur lÀnge webblÀsaren cachar resultaten frÄn preflight-förfrÄgan.
Alternativ till CORS
Ăven om CORS Ă€r standardmetoden för att möjliggöra förfrĂ„gningar mellan olika ursprung, finns det nĂ„gra alternativ som du kan övervĂ€ga i vissa scenarier:
1. JSON med Padding (JSONP)
JSONP Àr en teknik som anvÀnder <script>-taggen för att kringgÄ samma ursprungsprincip. JSONP fungerar genom att slÄ in JSON-data i ett JavaScript-funktionsanrop. WebblÀsaren exekverar sedan JavaScript-funktionen och skickar JSON-datan som ett argument. JSONP Àr enklare att implementera Àn CORS, men det har vissa begrÀnsningar. Det stöder endast GET-förfrÄgningar, och det Àr mindre sÀkert Àn CORS.
2. OmvÀnd proxy
En omvÀnd proxy Àr en server som sitter framför din API-server och vidarebefordrar förfrÄgningar till den. Den omvÀnda proxyn kan konfigureras för att lÀgga till nödvÀndiga CORS-headers i svaret, vilket effektivt döljer förfrÄgningarna mellan olika ursprung frÄn webblÀsaren. Detta tillvÀgagÄngssÀtt kan vara anvÀndbart om du inte har kontroll över API-servern eller om du vill förenkla CORS-konfigurationen.
Slutsats
Cross-Origin Resource Sharing (CORS) Àr en avgörande sÀkerhetsmekanism som gör att webbsidor kan komma Ät resurser frÄn olika ursprung pÄ ett kontrollerat sÀtt. Att förstÄ hur CORS fungerar och implementera det korrekt Àr avgörande för att bygga sÀkra och pÄlitliga webbapplikationer. Genom att följa de bÀsta praxis som beskrivs i denna artikel kan du effektivt hantera CORS och skydda dina API:er frÄn obehörig Ätkomst.
Kom ihÄg att alltid prioritera sÀkerhet nÀr du konfigurerar CORS. Undvik att anvÀnda jokertecken, validera Origin-headern och anvÀnd HTTPS för sÀker kommunikation. Genom att vidta dessa försiktighetsÄtgÀrder kan du sÀkerstÀlla att dina webbapplikationer Àr skyddade mot cross-site-attacker.
Denna omfattande guide ger en solid grund för att förstÄ CORS. Se alltid till att konsultera den officiella dokumentationen för din specifika server-side-teknik för den mest uppdaterade informationen och bÀsta praxis. HÄll dig informerad om nya sÀkerhetshot och anpassa din CORS-konfiguration dÀrefter.